﻿using System;
using System.Collections.Generic;
using System.Linq;
using Windows.UI.Xaml;
using XamlInspector.Foundation;
using XamlInspector.Model;
using XamlInspector.Model.Properties;

namespace XamlInspector.Presentation
{
    public class PropertiesViewModel : ViewModelBase
    {
        private readonly List<XamlProperty> _properties = new List<XamlProperty>();
        private string _filter;
        private readonly DispatcherTimer _refreshTimer = new DispatcherTimer();
        private bool _showLocalValuesOnly;
        private bool _showChangedValuesOnly;

        public PropertiesViewModel()
        {
            Properties = new ListCollectionView(_properties);
            Properties.Filter = FilterAction;

            _refreshTimer.Interval = TimeSpan.FromMilliseconds(50);
            _refreshTimer.Tick += (s, e) => UpdatePropertyValues();
            _refreshTimer.Start();

            ShowLocalValuesOnly = false;
        }

        public bool IsDataContext { get; set; }

        public bool ShowLocalValuesOnly
        {
            get { return _showLocalValuesOnly; }
            set
            {
                _showLocalValuesOnly = value;
                Properties.Refresh();
            }
        }

        public bool ShowChangedValuesOnly
        {
            get { return _showChangedValuesOnly; }
            set
            {
                _showChangedValuesOnly = value;
                Properties.Refresh();
            }
        }

        public void UpdateSelectedElement(XamlElement element)
        {
            using (Properties.DeferRefresh())
            {
                _properties.Clear();

                if (element == null)
                {
                    return;
                }

                if (IsDataContext)
                {
                    var dataContext = element.Properties.FirstOrDefault(p => p.Name == "DataContext") as XamlCompositeProperty;
                    if (dataContext != null)
                    {
                        _properties.AddRange(dataContext.Properties);
                    }
                }
                else
                {
                    _properties.AddRange(element.Properties);
                }
            }
        }

        public string Filter
        {
            get { return _filter; }
            set
            {
                ChangeAndNotify(value, ref  _filter);
                Properties.Refresh();
            }
        }

        public ICollectionViewEx Properties { get; private set; }

        private void UpdatePropertyValues()
        {
            Properties.Cast<XamlProperty>().ForEach(p => p.Refresh());
        }

        private bool FilterAction(object obj)
        {
            bool isVisible = true;

            var property = obj as XamlProperty;

            if (property == null)
            {
                return false;
            }

            if (string.IsNullOrWhiteSpace(Filter) == false)
            {
                isVisible &= property.Name.ToLower().Contains(Filter.ToLower());
            }

            if (ShowLocalValuesOnly)
            {
                isVisible &= property.IsLocalValue;
            }

            return isVisible;
        }
    }
}
